#pragma once
#include <cstddef>
#include <string>
#include <vector>
#include "InnerType.h"
#include "XnccServer.h"
#include "XnccType.h"
#include "flat_hash_map"
namespace xncc {
namespace foundation {
    class EventLoop;
    class XnccAddress;
    class Acceptor;
    class StreamSocketChannel;
    class SubStreamServer;
    class StreamServer final : public XnccServer
    {
      public:
        enum Option
        {
            kNoReusePort,
            kReusePort,
        };

        StreamServer(EventLoop*                   loop,
                     std::shared_ptr<XnccAddress> listenAddr,
                     std::string                  nameArg,
                     const std::set<std::string>& blacklist,
                     Option                       option = kNoReusePort);
        ~StreamServer() override;

        StreamServer(const StreamServer&)             = delete;
        StreamServer(const StreamServer&&)            = delete;
        StreamServer& operator=(const StreamServer&)  = delete;
        StreamServer& operator=(const StreamServer&&) = delete;

        void               init() override;
        void               start() override;
        [[nodiscard]] auto Type() const -> shared::XNCC_SERVER_TYPE override
        {
            return shared::XNCC_SERVER_TYPE::STREAM;
        }

        [[nodiscard]] const std::string& ipPort() const { return ipPort_; }
        [[nodiscard]] const std::string& name() const { return name_; }
        [[nodiscard]] EventLoop*         getLoop() const { return loop_; }
        void                             remove(types::connection_id_t connId) { clientChs_.erase(connId); }

      private:
        void createSubServer();

        void newConnection(int sockfd, std::shared_ptr<XnccAddress> peerAddr);

        void handleNewConnection(int sockfd, std::shared_ptr<XnccAddress> peerAddr);

        void removeConnection(types::connection_id_t connId, const std::string& reason);

        void handleIoMsg(const char* msg, uint32_t len, types::thread_id_t tid, types::connection_id_t connId);
        /// Thread safe.
        EventLoop*                loop_;  // the acceptor loop
        const std::string         ipPort_;
        const std::string         name_;
        std::unique_ptr<Acceptor> acceptor_;  // avoid revealing Acceptor
        // always in loop thread
        int nextConnId_;

        std::vector<std::shared_ptr<SubStreamServer>> subServers_;

        size_t nextSubserverIndex_;

        // 这个设计是一个server使用一个线程
        ska::flat_hash_map<types::connection_id_t, std::shared_ptr<StreamSocketChannel>> clientChs_;
    };
}  // namespace foundation
}  // namespace xncc